﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Chapter12
{
    using System.Drawing;
    using System.Collections;
    using System.Diagnostics;
    using DateTimeList = System.Collections.Generic.List<DateTime>;

    partial class Program
    {
        internal static void Begin(Action action, bool active = false)
        {
            if (active)
            {
                Console.WriteLine("开始演示：");
                action();
                Console.WriteLine("演示完毕：");
                Console.ReadLine();
            }
        }

        internal static void C01()
        {
            SomeMethod();
            ValueTypePerfTest();
            ReferenceTypePerfTest();
            byte[] byteArray = new byte[] { 5, 1, 4, 2, 3 };
            Array.Sort<byte>(byteArray);
            int i = Array.BinarySearch<byte>(byteArray, 1);
        }

        private static void SomeMethod()
        {
            List<DateTime> dtList = new List<DateTime>();
            dtList.Add(DateTime.Now);
            dtList.Add(DateTime.MinValue);
            //dtList.Add("1/1/2004");
            DateTime dt = dtList[0];
        }

        private static void ValueTypePerfTest()
        {
            const int count = 10000000;
            using (new OperationTimer("List<int>"))
            {
                List<int> v = new List<int>();
                for (int i = 0; i < count; i++)
                {
                    v.Add(i);
                    int x = v[i];
                }
                v = null;
            }
            using (new OperationTimer("ArrayList of int"))
            {
                ArrayList v = new ArrayList();
                for (int i = 0; i < count; i++)
                {
                    v.Add(i);
                    int x = (int)v[i];
                }
                v = null;
            }
        }

        private static void ReferenceTypePerfTest()
        {
            const int count = 10000000;
            using (new OperationTimer("List<string>"))
            {
                List<string> s = new List<string>();
                for (int i = 0; i < count; i++)
                {
                    s.Add("X");
                    string x = s[i];
                }
                s = null;
            }
            using (new OperationTimer("ArrayList of string"))
            {
                ArrayList s = new ArrayList();
                for (int i = 0; i < count; i++)
                {
                    s.Add("X");
                    string x = (string)s[i];
                }
                s = null;
            }
        }

        private sealed class OperationTimer : IDisposable
        {
            private Int64 startTime;
            private string text;
            private int collectionCount;

            internal OperationTimer(string text)
            {
                this.text = text;
                collectionCount = GC.CollectionCount(0);
                startTime = Stopwatch.GetTimestamp();
            }

            public void Dispose()
            {
                PrepareForOpertion();
                Console.WriteLine("{0,6:###.00} seconds (GCs={1,3}) {2}", (Stopwatch.GetTimestamp() - startTime) / (double)Stopwatch.Frequency, GC.CollectionCount(0) - collectionCount, text);
            }

            private static void PrepareForOpertion()
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
            }
        }

        internal static void C02()
        {
            object o = null;
            Type t = typeof(DictionaryStringKey<>);
            o = CreateInstance(t);
            Console.WriteLine();
            t = typeof(DictionaryStringKey<>);
            o = CreateInstance(t);
            Console.WriteLine();
            t = typeof(DictionaryStringKey<Guid>);
            o = CreateInstance(t);
            Console.WriteLine("对象类型=", o.GetType());
        }

        private sealed class DictionaryStringKey<TValue> : Dictionary<string, TValue>
        {

        }

        private static object CreateInstance(Type t)
        {
            object o = null;
            try
            {
                o = Activator.CreateInstance(t);
                Console.WriteLine("已创建 {0} 的实例：", t.ToString());
            }
            catch (ArgumentException e)
            {
                Console.WriteLine(e.Message);
            }
            return o;
        }

        private sealed class GenericTypeThatRequiresAnEnum<T>
        {
            static GenericTypeThatRequiresAnEnum()
            {
                if (!typeof(T).IsEnum)
                {
                    throw new ArgumentException("T must be an enumerated type");
                }
            }
        }

        private sealed class Node<T>
        {
            internal T data;
            internal Node<T> next;

            internal Node(T data)
                : this(data, null)
            {

            }

            internal Node(T data, Node<T> next)
            {
                this.data = data;
                this.next = next;
            }

            public override string ToString()
            {
                return data.ToString() + ((next != null) ? next.ToString() : null);
            }
        }

        private static void SameDataLinkedList()
        {
            Node<char> head = new Node<char>('C');
            head = new Node<char>('B', head);
            head = new Node<char>('A', head);
            Console.WriteLine(head.ToString());
        }

        internal static void C03()
        {
            SameDataLinkedList();
            List<DateTime> dt = new List<DateTime>();
            bool sameType = (typeof(List<DateTime>) == typeof(DateTimeList));
            Console.WriteLine(sameType);
        }

        private sealed class Triangel : IEnumerator<Point>
        {
            private Point[] vertices = new Point[10];

            public Point Current
            {
                get { return vertices[0]; }
            }

            public void Dispose()
            {
                throw new NotImplementedException();
            }

            object IEnumerator.Current
            {
                get { throw new NotImplementedException(); }
            }

            public bool MoveNext()
            {
                throw new NotImplementedException();
            }

            public void Reset()
            {
                throw new NotImplementedException();
            }
        }

        private sealed class ArrayEnumerator<T> : IEnumerator<T>
        {
            private T[] array = new T[20];

            public T Current
            {
                get { throw new NotImplementedException(); }
            }

            public void Dispose()
            {
                throw new NotImplementedException();
            }

            object IEnumerator.Current
            {
                get { throw new NotImplementedException(); }
            }

            public bool MoveNext()
            {
                throw new NotImplementedException();
            }

            public void Reset()
            {
                throw new NotImplementedException();
            }
        }

        private delegate TReturn CallMe<TReturn, TKey, TValue>(TKey key, TValue vale);

        internal static void C06()
        {
            Func<object, ArgumentException> fn1 = null;
            Func<string, Exception> fn2 = fn1;
        }

        private sealed class GenericType<T>
        {
            private T value;

            internal GenericType(T value)
            {
                this.value = value;
            }

            internal TOutput Converter<TOutput>()
            {
                TOutput result = (TOutput)Convert.ChangeType(value, typeof(TOutput));
                return result;
            }
        }

        private static void Swap<T>(ref T o1, ref T o2)
        {
            T temp = o1;
            o1 = o2;
            o2 = temp;
        }

        private static void CallingSwap()
        {
            int n1 = 1, n2 = 2;
            Console.WriteLine("n1={0}, n2={1}", n1, n2);
            Swap(ref n1, ref n2);
            Console.WriteLine("n1={0}, n2={1}", n1, n2);
            string s1 = "Aidan", s2 = "Kristin";
            Console.WriteLine("s1={0}, s2={1}", s1, s2);
            Swap(ref s1, ref s2);
            Console.WriteLine("s1={0}, s2={1}", s1, s2);
        }

        internal static void C07()
        {
            CallingSwap();
        }

        private static void Display(string s)
        {
            Console.WriteLine(s);
        }

        private static void Display<T>(T s)
        {
            Display(s.ToString());
        }

        internal static void C08()
        {
            Display("Jeff");
            Display(123);
            Display<string>("Aidan");
        }

        private static bool MethodTakingAnyType<T>(T o)
        {
            T temp = o;
            Console.WriteLine(o.ToString());
            bool b = temp.Equals(o);
            return b;
        }

        private static T Min<T>(T o1, T o2)
            where T : IComparable<T>
        {
            if (o1.CompareTo(o2) < 0)
                return o1;
            return o2;
        }

        private static void CallMin()
        {
            string o1 = "Jeff", o2 = "Richter";
            string oMin = Min(o1, o2);
        }

        private sealed class AType { }
        private sealed class AType<T> { }
        private sealed class AType<T1, T2> { }

        private sealed class AnotherType
        {
            private static void M() { }
            private static void M<T>() { }
            private static void M<T1, T2>() { }
        }

        private class Base
        {
            internal virtual void M<T1, T2>()
                where T1 : struct
                where T2 : class { }
        }

        private sealed class Derived : Base
        {
            internal override void M<T3, T4>()
            {
                base.M<T3, T4>();
            }
        }

        private sealed class PrimaryConstraintOfStream<T> where T : System.IO.Stream
        {
            internal void M(T stream)
            {
                stream.Close();
            }
        }

        private sealed class PrimaryConstraintOfClass<T> where T : class
        {
            internal void M()
            {
                T temp = null;
                Console.WriteLine(temp);
            }
        }

        private sealed class PrimaryConstraintOfStruct<T> where T : struct
        {
            internal static T Factory()
            {
                return new T();
            }
        }

        private static List<TBase> ConvertIList<T, TBase>(IList<T> list) where T : TBase
        {
            List<TBase> baseList = new List<TBase>(list.Count);
            for (int i = 0; i < list.Count; i++)
            {
                baseList.Add(list[i]);
            }
            return baseList;
        }

        private static void CallingConverterList()
        {
            List<string> ls = new List<string>();
            ls.Add("A String");
            IList<object> lo = ConvertIList<string, object>(ls);
            IList<IComparable> lc = ConvertIList<string, IComparable>(ls);
            IList<IComparable<string>> lcs = ConvertIList<string, IComparable<string>>(ls);
            IList<string> ls2 = ConvertIList<string, string>(ls);
        }

        private sealed class ConstructorConstraint<T> where T : new()
        {
            internal static T Factory()
            {
                return new T();
            }
        }
    }
}
